from flask import Blueprint, request, jsonify
from flask_jwt_extended import jwt_required, get_jwt_identity
from model import Course, Exam, StudentExam, StudentCourse, Question  # Import necessary models
from extension import db  # Assuming you're using Flask-SQLAlchemy
from datetime import datetime
from model import Exam, User, ExamRecord

exam_bp = Blueprint('exam', __name__)


@exam_bp.route('/create_exam/<course_id>', methods=['POST'])
@jwt_required()
def create_exam(course_id):
    """
    Teacher creates an exam for a specific course.
    Expects a JSON body with exam details (title, exam_date, duration, questions).
    """
    data = request.json
    title = data.get('title')
    start_time = data.get('start_time')  # Expecting ISO format date
    end_time = data.get('end_time')  # Duration in minutes
    questions = data.get('questions')  # List of questions (MCQ, True/False, Short Answer)

    if not title or not start_time or not end_time or questions is None:
        return jsonify({'msg': 'Title, exam date, duration, and questions are required'}), 400

    try:
        start_time = datetime.fromisoformat(start_time)
        end_time = datetime.fromisoformat(end_time)
    except ValueError:
        return jsonify({'msg': 'Invalid exam date format. Use ISO format.'}), 400

    new_exam = Exam(course_id=course_id, test_title=title, start_time=start_time, end_time=end_time, total_grade=100)
    db.session.add(new_exam)
    db.session.commit()
    for question in questions:
        question_type = question.get('type')  # e.g., 'multiple_choice', 'true_false', 'short_answer'
        question_content = question.get('content')
        correct_answer = question.get('correct_answer')
        score = question.get('score')
        # For multiple-choice questions, we expect options to be present
        options = question.get(
            'options') if question_type == 'multiple_choice' or question_type == "single_choice" else None

        if question_type == 'multiple_choice' and not options:
            return jsonify({'msg': 'Options are required for multiple-choice questions'}), 400

        new_question = Question(
            exam_id=new_exam.test_id,
            q_type=question_type,
            content=question_content,
            correct_answer=correct_answer,
            options=options,
            score=score
        )
        db.session.add(new_question)

    db.session.commit()

    return jsonify({'msg': 'Exam created successfully', 'exam_id': new_exam.test_id}), 201


@exam_bp.route('/view_exam_list/<course_id>', methods=['GET'])
@jwt_required()
def view_exam_list(course_id):
    """
    View exam list for a specific course.
    """
    exams = Exam.query.filter_by(course_id=course_id).all()
    if not exams:
        return jsonify({'msg': 'No exams found for this course'}), 200

    user = get_jwt_identity()
    uid = None
    if user['role'] == 'student':
        uid = user['uid']

    exam_list = []
    exam_record = None
    for exam in exams:
        if uid is not None:
            exam_record = ExamRecord.query.filter_by(test_id=exam.test_id, student_id=uid).first()
        exam_list.append({
            'exam_id': exam.test_id,
            'title': exam.test_title,
            'start_time': exam.start_time,
            'end_time': exam.end_time,
            'grade': exam_record.score if exam_record else None,

        })
    return jsonify(exam_list), 200


@exam_bp.route('/view_exam_detail/<exam_id>', methods=['GET'])
@jwt_required()
def get_exam_details(exam_id):
    """
    Get details for a specific exam.
    """
    exam = Exam.query.filter_by(test_id=exam_id).first()
    if not exam:
        return jsonify({'msg': 'Exam not found'}), 404

    questions = Question.query.filter_by(exam_id=exam.test_id).all()

    question_list = [{
        'type': q.q_type,
        'content': q.content,
        'options': q.options if q.options else None,
        'score': q.score  # Include score in each question
    } for q in questions]

    exam_details = {
        'exam_id': exam.test_id,
        'title': exam.test_title,
        'start_time': exam.start_time,
        'end_time': exam.end_time,
        'questions': question_list
    }

    return jsonify(exam_details), 200

@exam_bp.route('/submit_exam/<course_id>', methods=['POST'])
@jwt_required()
def submit_exam(course_id):
    """
    Student submits their exam for a specific course.
    Expects a JSON body with exam submission details (exam_id, answers).
    """
    data = request.json
    exam_id = data.get('exam_id')
    answers = data.get('answers')  # Answers submitted by the student

    if not exam_id or answers is None:
        return jsonify({'msg': 'Exam ID and answers are required'}), 400

    # Check if the exam exists and is associated with the course
    exam = Exam.query.filter_by(test_id=exam_id, course_id=course_id).first()
    if not exam:
        return jsonify({'msg': 'Exam not found for this course'}), 404

    student_id = get_jwt_identity()['uid']  # Assuming the student ID is stored in the JWT

    # Validate the answers format
    if not isinstance(answers, list):
        return jsonify({'msg': 'Answers must be a list.'}), 400

    # Save the exam submission in the database

    questions = Question.query.filter_by(exam_id=exam_id).all()
    score = 0
    short_answer_responses = {}

    for i, question in enumerate(questions):
        if i < len(answers):
            if question.q_type == 'multiple_choice' or question.q_type == 'single_choice' or question.q_type == 'boolean':
                # Automatically grade multiple choice questions
                if answers[i] == question.correct_answer:
                    score += question.score  # Assuming score is a float
            elif question.q_type == 'short_answer':
                # Store short answer responses for manual grading
                short_answer_responses[question.id] = answers[i]

    # Save the exam submission in the database
    try:
        student_exam = StudentExam(
            student_id=student_id,
            exam_id=exam_id,
            answers=answers,  # Store all answers as JSON text
            short_answers=short_answer_responses,
            submission_date=datetime.utcnow()
        )
        db.session.add(student_exam)

        # Save the score in ExamRecord
        exam_record = ExamRecord(
            student_id=student_id,
            test_id=exam_id,
            correct_condition="Pending" if short_answer_responses else "Completed",
            score=score  # Save the auto-graded score only
        )
        db.session.add(exam_record)

        db.session.commit()

        # Return the score for automatically graded questions and indicate that short answer responses await grading
        return jsonify({
            'msg': 'Exam submitted successfully',
            'score': score,
            'short_answer_responses': short_answer_responses  # To notify which questions require grading
        }), 201

    except Exception as e:
        db.session.rollback()  # Rollback in case of any error
        return jsonify({'msg': 'Error saving exam submission', 'error': str(e)}), 500


@exam_bp.route('/grade_exam/<int:exam_id>', methods=['POST'])
@jwt_required()
def grade_exam(exam_id):
    data = request.json
    grades = data.get('grades')

    if not grades or not isinstance(grades, dict):
        return jsonify({'msg': 'Grades data is required and must be a dictionary.'}), 400

    # Verify that the exam exists
    exam = Exam.query.filter_by(test_id=exam_id).first()
    if not exam:
        return jsonify({'msg': 'Exam not found.'}), 404

    # Iterate through each student_id and score provided
    for student_id, score in grades.items():
        # Verify that the student exists
        student = User.query.filter_by(student_id=student_id).first()
        if not student:
            return jsonify({'msg': f'Student {student_id} not found.'}), 404

        # Check if an ExamRecord already exists for this student and exam
        exam_record = ExamRecord.query.filter_by(student_id=student_id, test_id=exam_id).first()

        if exam_record:
            # Update existing record if found
            exam_record.score += score
        else:
            # Create a new ExamRecord if none exists
            new_exam_record = ExamRecord(
                student_id=student_id,
                test_id=exam_id,
                correct_condition="graded",  # assuming "graded" means it’s marked by the teacher
                score=score
            )
            db.session.add(new_exam_record)

    # Commit all changes to the database
    db.session.commit()

    return jsonify({'msg': 'Grades updated successfully'}), 200


@exam_bp.route('/view_submissions/<int:exam_id>', methods=['GET'])
@jwt_required()
def view_submissions(exam_id):
    """
    View submissions for a specific exam, showing details of each student's answers by question type.
    """
    # 获取考试信息
    exam = Exam.query.filter_by(test_id=exam_id).first()
    if not exam:
        return jsonify({'msg': 'Exam not found.'}), 404

    # 获取所有提交记录
    submissions = StudentExam.query.filter_by(exam_id=exam_id).all()
    submission_details = []

    # 遍历每个提交记录
    for submission in submissions:
        student = User.query.filter_by(student_id=submission.student_id).first()
        if student:
            # 获取考试中的所有题目
            questions = Question.query.filter_by(exam_id=exam_id).all()

            # 提取答案信息
            answers = submission.answers  # 假设是 JSON 字符串，存储选择题和判断题的答案
            short_answers = submission.short_answers  # 假设是 JSON 字段，存储简答题的答案
            question_answers = []

            # 为每道题整理答案
            for question in questions:
                if question.q_type == 'multiple_choices' or question.q_type == 'true_false':
                    # 从答案 JSON 中提取对应的选择题或判断题答案
                    answer = answers.get(str(question.id)) if answers else None
                    question_answers.append({
                        'question_id': question.id,
                        'type': question.q_type,
                        'content': question.content,
                        'options': question.options,
                        'score': question.score,
                        'correct_answer': question.correct_answer,  # 正确答案
                        'student_answer': answer  # 学生的选择或判断答案
                    })
                elif question.q_type == 'short_answer':
                    # 从简答题答案 JSON 中提取对应的答案
                    short_answer = short_answers.get(str(question.id)) if short_answers else None
                    question_answers.append({
                        'question_id': question.id,
                        'type': question.q_type,
                        'content': question.content,
                        'score': question.score,
                        'correct_answer': question.correct_answer,  # 正确答案
                        'student_answer': short_answer  # 学生的简答题答案
                    })

            # 组织提交信息
            submission_info = {
                'student_id': student.student_id,
                'student_name': student.name,
                'question_answers': answers,  # 包含每道题的详细信息和学生的答案
                'image_path': submission.image_path,  # 假设此字段存在
                'submission_date': submission.submission_date
            }
            submission_details.append(submission_info)

    return jsonify({'submissions': submission_details}), 200


@exam_bp.route('/teacher_view_exam/<int:exam_id>', methods=['GET'])
@jwt_required()
def teacher_view_exam(exam_id):
    """
    Allows a teacher to view the exam details, including the correct answers for each question.
    """
    exam = Exam.query.filter_by(test_id=exam_id).first()
    if not exam:
        return jsonify({'msg': 'Exam not found.'}), 404

    # Get all questions associated with the exam
    questions = Question.query.filter_by(exam_id=exam.test_id).all()

    question_list = [{
        'question_id': question.id,
        'type': question.q_type,
        'content': question.content,
        'options': question.options if question.options else None,
        'correct_answer': question.correct_answer,  # Include the correct answer for teachers
        'score': question.score
    } for question in questions]

    # exam_details = {
    #     'exam_id': exam.test_id,
    #     'title': exam.test_title,
    #     'start_time': exam.start_time,
    #     'end_time': exam.end_time,
    #     'questions': question_list
    # }

    return jsonify({'exam_id': exam.test_id,
                    'title': exam.test_title,
                    'start_time': exam.start_time,
                    'end_time': exam.end_time,
                    'questions': question_list}), 200


@exam_bp.route('/delete_exam/<int:exam_id>', methods=['POST'])
@jwt_required()
def delete_exam(exam_id):
    """
    Allows a teacher to delete a specific exam and all associated data (e.g., questions, records, submissions).
    """
    user = get_jwt_identity()

    # 检查是否为教师权限
    if user.get('role') != 'teacher':
        return jsonify({'msg': 'Unauthorized. Only teachers can delete exams.'}), 403

    # 查找考试
    exam = Exam.query.filter_by(test_id=exam_id).first()
    if not exam:
        return jsonify({'msg': 'Exam not found.'}), 404

    try:
        # 删除与考试相关的所有问题
        Question.query.filter_by(exam_id=exam_id).delete()

        # 删除学生提交记录
        StudentExam.query.filter_by(exam_id=exam_id).delete()

        # 删除考试成绩记录
        ExamRecord.query.filter_by(test_id=exam_id).delete()

        # 删除考试本身
        db.session.delete(exam)

        # 提交更改到数据库
        db.session.commit()

        return jsonify({'msg': 'Exam deleted successfully.'}), 200

    except Exception as e:
        db.session.rollback()  # 如果出现错误，回滚事务
        return jsonify({'msg': 'Error deleting exam.', 'error': str(e)}), 500
